/******************************************************************************
 * Copyright 2022 The Airos Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "base/device_connect/camera/device_factory.h"

#include "gtest/gtest.h"

#include <cassert>
#include <iostream>
#include <string>

namespace os {
namespace v2x {
namespace device {

static std::stringstream g_camera_cout_buf;
void proc_camera_stream_data(const std::string& camera_name,
                             const uint8_t* data, size_t size) {
  std::cout << camera_name;
}

class CameraTest : public ::testing::Test {
 public:
  CameraTest() : device_(nullptr), sbuf_(nullptr) {}
  virtual ~CameraTest() {}
  virtual void SetUp() {
    sbuf_ = std::cout.rdbuf();
    std::cout.rdbuf(g_camera_cout_buf.rdbuf());
  }
  virtual void TearDown() {
    std::cout.rdbuf(sbuf_);
    sbuf_ = nullptr;
  }

 protected:
  std::shared_ptr<CameraDevice> device_;
  std::streambuf* sbuf_;
};

TEST_F(CameraTest, test_all_interface) {
  device_ = CameraDeviceFactory::Instance().GetUnique("dummy_camera",
                                                      proc_camera_stream_data);
  ASSERT_NE(device_, nullptr);
  ASSERT_TRUE(device_->Init("/airos/base/device_connect/camera/ut/camera.cfg"));

  std::string expect{"camera1camera2camera3"};
  std::string res = g_camera_cout_buf.str();
  EXPECT_EQ(expect, res);

  auto camera1_data = device_->GetImage("camera1");
  ASSERT_NE(camera1_data, nullptr);
  EXPECT_EQ(camera1_data->sequence_num, 1);

  auto camera2_data = device_->GetImage("camera2");
  ASSERT_NE(camera2_data, nullptr);
  EXPECT_EQ(camera2_data->sequence_num, 2);

  auto camera3_data = device_->GetImage("camera3");
  ASSERT_NE(camera3_data, nullptr);
  EXPECT_EQ(camera3_data->sequence_num, 3);

  EXPECT_EQ(CameraDeviceState::UNKNOWN, device_->GetState("camera1"));
  EXPECT_EQ(CameraDeviceState::RUNNING, device_->GetState("camera2"));
  EXPECT_EQ(CameraDeviceState::STOP, device_->GetState("camera3"));
}

TEST_F(CameraTest, test_init_failed) {
  device_ = CameraDeviceFactory::Instance().GetUnique("dummy_camera",
                                                      proc_camera_stream_data);
  ASSERT_NE(device_, nullptr);
  ASSERT_FALSE(device_->Init(
      "/airos/base/device_connect/camera/ut/camera.cfg-no-exists"));
}

TEST_F(CameraTest, test_non_register_camera) {
  device_ = CameraDeviceFactory::Instance().GetUnique("dummy_camera",
                                                      proc_camera_stream_data);
  ASSERT_NE(device_, nullptr);
  ASSERT_TRUE(device_->Init("/airos/base/device_connect/camera/ut/camera.cfg"));

  auto camera_non_register = device_->GetImage("cameraX");
  EXPECT_EQ(camera_non_register, nullptr);
  EXPECT_EQ(CameraDeviceState::NO_REGISTER, device_->GetState("cameraX"));
}

}  // namespace device
}  // namespace v2x
}  // namespace os
